fix(components): exclude test files from the published stylesheet's @source scan - #8453
Merged
Merged
Conversation
…source scan Tailwind v4 scans source TEXT, so `src/index.css`'s unrestricted `@source '../src/**/*.{ts,tsx}'` made all 243 test files under `src/**/__tests__/` sources for the published `dist/index.css`. A class-shaped token written as a test's expected value therefore compiled a real utility into the shipped bundle — a test could create the production utility it asserted on. Add the two `@source not` lines already used by `fields`, `plugin-grid` and `plugin-kanban`. Measured through this package's own postcss + `@tailwindcss/postcss` pipeline from the directory `pnpm build` runs in, eight rules are removed and none added: .flex-grow .flex-nowrap .h-[125px] .isolate .paused .shrink .text-green-500 .w-[250px]. Every one was named only by a test file; `.flex-grow` came from a prose JSDoc sentence about the CSS property. The guard test is self-hosted: its sentinel token lives in a file under `__tests__/`, so removing the exclusions makes the sentinel compile and the test go red. It is paired with a positive assertion because a stylesheet compiled from nothing would satisfy the negative half alone. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YBWFb5YgMU5dw8p2VKj16S
os-justin
marked this pull request as ready for review
September 8, 2026 00:25
os-justin
enabled auto-merge
September 8, 2026 00:25
Contributor
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
os-justin
deleted the
claude/issue-8446-components-css-excludes-tests
branch
September 8, 2026 00:55
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #8446
Tailwind v4 scans source text, not an import graph.
packages/components/src/index.cssdeclared
@source '../src/**/*.{ts,tsx}'with no exclusion, so all 243 test files undersrc/**/__tests__/were sources for the publisheddist/index.css. A class-shaped tokenwritten as a test's expected value therefore compiled a real utility into the shipped
bundle — which is how a test can create the production utility it is asserting on.
The single cleanest instance found here is not a fixture but an assertion:
.text-green-500shipped indist/index.cssbecause that assertion names it.Two
@source notlines are added, matching the spelling already used byfields,plugin-gridandplugin-kanban.The measurement
src/index.csscompiled through this package's own pipeline —postcss([tailwindPostcss()]),i.e. step 2 of
packages/components/scripts/build-css.mjs— and everyRulenode collectedwith its at-rule ancestry. Diffing rule sets, not counting them.
File set on disk for both readings (this is the step whose omission would make the table
dishonest — the compile is sensitive to what is on disk, not to what is committed):
0b1ac58a66ee8ee0ddc59e0fa73301f8647ffbf6;git status --porcelainover
packages/components/srcempty for the before reading..ts/.tsxfiles underpackages/components/src, 243 of them test-shaped.@source notlines. The new guard testfile was added afterwards and verified not to change the sheet (byte-identical rule set),
so it does not contaminate the table.
src/index.cssopens with a bare@import 'tailwindcss', so Tailwind's automatic sourcedetection is ON and — as
packages/fields/src/index.cssalready documents — resolves againstthe process CWD. Same commit, same bytes, two artifacts:
packages/components(wherepnpm buildruns — authoritative)A repo-root reading would have under-reported this PR's removal by five of eight classes —
they survive there only because other packages' sources also name them. The table below is
the package-CWD one.
What disappears — the rule diff
Removed (8). Added (0).
Per-class verdict: does any non-test source name it?
The compile diff defines the answer — a rule that disappears when test files stop being
scanned is by construction sourced only from test files. The greps below say which text
produced it. All eight: no production namer.
.text-green-500icon-unresolvable-placeholder.test.tsx:141,146— aclassNamefixture and thetoContainexpected value.h-[125px]snapshot-critical.test.tsx:321— aSkeletonelement withclassName="h-[125px] w-[250px] …"+ committed snapshot.w-[250px]snapshot-critical.test.tsx:309,321,323+ committed snapshot.flex-growform-field-panes.test.tsx:25— prose in a JSDoc comment about the CSS propertyflex-grow: 50.flex-nowrappage-header-title-width.test.tsx:6— prose in a JSDoc comment.pauseddialog-popover-focus-scope.test.tsx:76— a//code comment.isolate__tests__prose about Vitest'sisolate: true.shrinkcombobox-long-label.test.tsx:34,36— a test title and a commentFour of the eight were compiled out of English prose in comments. None was ever authored
as styling.
Does removing them bite anyone?
apps/console,examples/console-starter,examples/byo-backend-consoleall@sourcethe packagesrcdirs) — generate utilities from their own markup and are unaffected.
under ADR-0065 (
content/docs/guide/react-pages.md) states a utility class in page source"produces CSS only if that exact class happens to already appear in objectui's own source",
and
os validatewarnspage-source-className-tailwind. That incidental "happens toappear" is precisely what is being removed.
@object-ui/components/style.css, running no Tailwind of its own, hand-writing one of theeight in its own JSX.
.isolate,.shrink,.flex-nowrap,.text-green-500are plausiblethere.
.flex-growand.shrinkalso have surviving canonical spellings —.growand.shrink-0stay in the sheet, and this repo already migratedflex-grow-N→grow-Ndeliberately.
That residual case is why the changeset is
minorrather thanpatch.Proving the change can fail
The instrument is the compiled stylesheet, so the ablation restores the unrestricted
@sourceand recompiles. Run from the committed implementation (336bd7a4), tree clean,with a
trap ... EXIT INT TERMholding absolute paths.Mutation proven on disk, not by an exit code:
@source notlines 2 → 0;git hash-object50c2d90fvsgit rev-parse HEAD:packages/components/src/index.css=75153ac5.Both legs fire:
.mt-\[3\.7331px\]: the guard test's own sentinel. That is the defect reproducing live onthis PR's own new test file, and it is what proves the probe is not inert.
vitestexits 1 onAssertionError: expected '/*! tailwindcss v4.3.3 …' not to contain '3.7331px'.Restore proven by state:
git diff HEADempty,git hash-objectback to75153ac5,@source notlines back to 2 — then the guard test passes again.No
dist/rebuild is involved: the reading compilessrc/index.cssfresh each time, so thereis no stale-artifact leg to get wrong here.
The guard test
src/__tests__/index-css-scan-excludes-tests.test.tscompiles the stylesheet and assertsboth directions, because a stylesheet compiled from nothing satisfies "no test-sourced
rules" — an implementation strictly worse than this fix (delete the
@sourceline) would passa negative-only test.
mt-[3.7331px], absent everywhere else inthe repo) is written in that test file itself, which lives under
__tests__/. The probeis self-hosted: remove the exclusions and the sentinel compiles and the test goes red. It
does not depend on any other test continuing to name a fixture class.
.flex-col(production-sourced) must be present, and the sheet must hold morethan 800 rules.
It passes
base: packageRootto@tailwindcss/postcssso the reading is CWD-independent —otherwise Vitest (repo root) and
pnpm build(package dir) would measure different artifacts,per the table above.
Out of scope — reported, not swept in (#8446 fences this to
components)search_issueswas rate-limited, so per the dispatch these are reported rather than filedunsearched. None is fixed here.
componentsis the only one of three missing this. There are more.Sweep of every
@sourcein the repo: excluding correctly —fields(filename only),plugin-grid(not mentioned in the issue),plugin-kanban. Missing exclusionsentirely —
packages/runner/src/index.css,apps/console/src/index.css,apps/site/app/global.css, and bothexamples/*/src/index.css.packages/runneris a published package that re-leaks these exact classes. Itsindex.cssscans../../packages/components/src/**with no test exclusion, so afterthis PR
@object-ui/runner's own published sheet still compiles the eight. Its line 10 alsoreads
@source './src/**/*.{ts,tsx}', which frompackages/runner/src/index.cssresolvesto
packages/runner/src/src/— a directory that does not exist.componentslackssource(none), so its published sheet is CWD-dependent (1385 vs 3430rules, table above) and non-shipped text is a source. Measured: adding
source(none)on top of this PR removes 23 further rules, including.flex-shrink-0,.bg-blue-500,.md:text-2xl,.hover:bg-blue-700:hoverand — from a doc comment —.origin-[--radix-…]with a literal Unicode ellipsis.fieldscalls its ownsource(none)"load-bearing, not tidiness" for exactly this reason. This PR's two lines are a strict
improvement but only a partial fix of the false-green generator; the complete fix is
sibling parity on
source(none), which is a materially larger bundle diff and its own card.packages/components/CHANGELOG.mdis a Tailwind source for the published bundle.Proven by injecting a unique token into it and recompiling.
.flex-shrink-0— a deprecatedv3 alias this repo deliberately migrated away from — ships today solely because the
changelog entry announcing its removal names it.
Changeset
.changeset/8446-components-css-excludes-test-sources.md—@object-ui/components: minor.node scripts/check-changeset-presence.mjs:Not empty-frontmatter: this changes published bundle contents. Not
patch: it removesbehaviour a narrow consumer could depend on, and this repo labels its own breaking changes
minor.majoris forbidden for the fixed group andscripts/check-changeset-no-major.mjspasses.🤖 Generated with Claude Code
https://claude.ai/code/session_01YBWFb5YgMU5dw8p2VKj16S
Generated by Claude Code